// Copyright (c) 2011 Blue Onion Software, All rights reserved
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Xml;
using BlueOnionSoftware.Bloget;
using NUnit.Framework;

namespace BlogetTests
{
    [TestFixture]
    [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
    public class MetaWeblogTests
    {
        [Test]
        public void ParseGetUsers()
        {
            var testCall =
                @"<?xml version=""1.0""?>
            <methodCall>
            <methodName>blogger.getUsersBlogs</methodName>
            <params><param><value><string>0123456789ABCDEF</string></value></param>
            <param><value><string>bloget</string></value></param>
            <param><value><base64>S2l0em1hbm4</base64></value></param>
            </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);
            Assert.IsTrue(methodCall.Name == Blogger.MethodGetUsersBlogs, "ParseGetUsers - methodCall");
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "0123456789ABCDEF",
                          "ParseGetUsers - methodCall.Parameters[0]");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget",
                          "ParseGetUsers - methodCall.Parameters[1]");
        }

        [Test]
        public void ParseGetPost()
        {
            var testCall =
                @"<?xml version=""1.0""?>
            <methodCall>
            	<methodName>metaWeblog.getPost</methodName>
            	<params>
            		<param>
            			<value>32a2d0b8-d8ed-4af2-aeed-0f9bfd1cde98</value>
            			</param>
            		<param>
            			<value>bloget</value>
            			</param>
            		<param>
            			<value>Franklin</value>
            			</param>
            		</params>
            	</methodCall>";

            var methodCall = ParseMethodCall(testCall);
            Assert.IsTrue(methodCall.Name == MetaWebLog.MethodGetPost, "ParseGetPost - methodCall");
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "32a2d0b8-d8ed-4af2-aeed-0f9bfd1cde98",
                          "ParseGetPost - methodCall.Parameters[0]");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget",
                          "ParseGetPost - methodCall.Parameters[1]");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin",
                          "ParseGetPost - methodCall.Parameters[2]");
        }

        [Test]
        public void ParseNewMediaObject()
        {
            var testCall =
                @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
            <methodCall>
               <methodName>metaWeblog.newMediaObject</methodName>
               <params>
               <param>
            <value><string>1</string></value>
               </param>
               <param>
            <value><string>bloget</string></value>
               </param>
               <param>
            <value><string>Franklin</string></value>
               </param>
               <param>
            <value>
              <struct>
                <member>
                  <name>bits</name>
                  <value><base64>R0lGODlhEAAQAMQfAPbcQ+K3OvTVPse6nf31Vrisl/jlStyrNMa+qMa0hfHKNeXJSuzBMvnqTfHOOtedM/fgRv76W6qPSvvvUtG3Xa+adOnVVPDHM8uxVwAAAPXeSXk+Fq5OKLWfR/////8A/yH5BAEAAB8ALAAAAAAQABAAAAWl4CeKSEJhCTKu32BBMCAvAzsYeINDgCAko5uh05lMdESBo/axDD2eDmHSgXYcgQ8C19lkOhFC9+tYJiCN7gYs3qwdigoFYqCCw3alQoIBGBoTBIJHBj0OFxIJABAagEY6PAIKFxUIPQ8OfzsAAQcXFwUfCwIHHAGLPQEcngciA0qlHLKyBwwMoSIFZQwPvQ8BFwwVNgEKk58MB7gsHwUVEhIVyyIhADs=</base64></value>
                </member>
                <member>
                  <name>name</name>
                  <value><string>/Blog/smile1.gif</string></value>
                </member>
                <member>
                  <name>type</name>
                  <value><string>application/octet-stream</string></value>
                </member>
              </struct>
            </value>
            
               </param>
               </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);
            Assert.IsTrue(methodCall.Name == MetaWebLog.MethodNewMediaObject);
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "1",
                          "ParseNewMediaObject - methodCall.Parameters[0]");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget",
                          "ParseNewMediaObject - methodCall.Parameters[1]");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin",
                          "ParseNewMediaObject - methodCall.Parameters[2]");

            var media = methodCall.Parameters[3].Value as XmlRpcStruct;

            Assert.IsNotNull(media);
            Assert.IsNotNull(media.Members[0].Value);
            Assert.IsTrue(media.Members[1].Value.ToString() == "/Blog/smile1.gif",
                          "ParseNewMediaObject - media.Members[1]");
            Assert.IsTrue(media.Members[2].Value.ToString() == "application/octet-stream",
                          "ParseNewMediaObject - media.Members[1]");
        }

        [Test]
        public void ParseNewPost()
        {
            var testCall =
                @"<?xml version=""1.0"" encoding=""UTF-8"" ?>
            <methodCall>
            <methodName>metaWeblog.newPost</methodName>
            <params>
            <param>
            <value><string>1</string></value>
            </param>
            <param>
            <value><string>bloget</string></value>
            </param>
            <param>
            <value><string>Franklin</string></value>
            </param>
            <param>
            <value><struct>
            <member>
            <name>dateCreated</name>
            <value><dateTime.iso8601>20061212T03:25:18Z</dateTime.iso8601></value>
            </member>
            <member>
            <name>text</name>
            <value><string>
            &lt;p&gt;Testing with Zoundary.&lt;/p&gt;
            &lt;p class=""poweredbyzoundry""&gt;Powered by &lt;a href=""http://www.zoundry.com"" class=""poweredbyzoundry_link"" rel=""nofollow""&gt;Zoundry&lt;/a&gt;&lt;/p&gt;</string></value>
            </member>
            <member>
            <name>categories</name>
            <value><array><data>
            <value><string>Bloget</string></value>
            </data></array></value>
            </member>
            <member>
            <name>title</name>
            <value><string>Test with Zoundary</string></value>
            </member>
            </struct></value>
            </param>
            <param>
            <value><boolean>1</boolean></value>
            </param>
            </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);
            Assert.IsTrue(methodCall.Name == MetaWebLog.MethodNewPost);
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "1");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin");

            var post = methodCall.Parameters[3].Value as XmlRpcStruct;
            Assert.IsNotNull(post);
            Assert.IsTrue((DateTime) post.Members[0].Value.Value ==
                new DateTime(2006, 12, 12, 3, 25, 18, DateTimeKind.Utc));
            Assert.IsTrue(post.Members[2].Name == "categories");
            Assert.IsTrue((string) post.Members[3].Value.Value == "Test with Zoundary");
            Assert.IsInstanceOf<XmlRpcArray>(post.Members[2].Value.Value);
            var array = (XmlRpcArray) post.Members[2].Value.Value;
            Assert.IsTrue((string) array.Values[0].Value == "Bloget");
        }

        [Test]
        public void ParseNewPost2()
        {
            const string testCall =
                @"<?xml version=""1.0"" encoding=""UTF-8"" ?><methodCall>
              <methodName>metaWeblog.newPost</methodName>
              <params>
                <param>
                  <value>
                    <string>1</string>
                  </value>
                </param>
                <param>
                  <value>
                    <string>bloget</string>
                  </value>
                </param>
                <param>
                  <value>
                    <string>Franklin</string>
                  </value>
                </param>
                <param>
                  <value>
                    <struct>
                      <member>
                        <name>title</name>
                        <value>
                          <string>Testing Performancing Plugin</string>
                        </value>
                      </member>
                      <member>
                        <name>text</name>
                        <value>
                          <string>&lt;br /&gt;Testing the Performancing blogging plugin. This is a FireFox extension.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p class=""poweredbyperformancing""&gt;powered by &lt;a href=""http://performancing.com/firefox""&gt;performancing firefox&lt;/a&gt;&lt;/p&gt;</string>
                        </value>
                      </member>
                      <member>
                        <name>categories</name>
                        <value>
                          <array>
                            <data/>
                          </array>
                        </value>
                      </member>
                    </struct>
                  </value>
                </param>
                <param>
                  <value>
                    <boolean>true</boolean>
                  </value>
                </param>
              </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);

            Assert.IsTrue(methodCall.Name == MetaWebLog.MethodNewPost);
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "1");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin");

            var post = methodCall.Parameters[3].Value as XmlRpcStruct;
            Assert.IsNotNull(post);
            Assert.IsTrue((string) post.Members[0].Value.Value == "Testing Performancing Plugin");
            Assert.IsTrue(post.Members[2].Name == "categories");
            Assert.IsInstanceOf<XmlRpcArray>(post.Members[2].Value.Value);
        }

        [Test]
        public void ParseNewPost3()
        {
            var testCall =
                @"<methodCall>
              <methodName>metaWeblog.newPost</methodName>
              <params>
                <param>
                  <value>
                    <string>1</string>
                  </value>
                </param>
                <param>
                  <value>
                    <string>bloget</string>
                  </value>
                </param>
                <param>
                  <value>
                    <string>Franklin</string>
                  </value>
                </param>
                <param>
                  <value>
                    <struct>
                      <member>
                        <name>text</name>
                        <value>
                          <string>Testing BlogMailr...</string>
                        </value>
                      </member>
                      <member>
                        <name>title</name>
                        <value>
                          <string>Testing BlogMailr</string>
                        </value>
                      </member>
                      <member>
                        <name>enclosure</name>
                        <value>
                          <struct>
                            <member>
                              <name>length</name>
                              <value>
                                <i4>0</i4>
                              </value>
                            </member>
                          </struct>
                        </value>
                      </member>
                      <member>
                        <name>source</name>
                        <value>
                          <struct />
                        </value>
                      </member>
                    </struct>
                  </value>
                </param>
                <param>
                  <value>
                    <boolean>1</boolean>
                  </value>
                </param>
              </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);

            Assert.IsTrue(methodCall.Name == MetaWebLog.MethodNewPost);
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "1");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin");

            var post = methodCall.Parameters[3].Value as XmlRpcStruct;
            Assert.IsNotNull(post);
            Assert.IsTrue((string) post.Members[1].Value.Value == "Testing BlogMailr");
            Assert.IsTrue(post.Members[2].Name == "enclosure");
            Assert.IsInstanceOf<XmlRpcStruct>(post.Members[2].Value.Value);
            var enclosure = (XmlRpcStruct) post.Members[2].Value.Value;
            Assert.IsTrue(enclosure.Members[0].Name == "length");
            Assert.IsInstanceOf<int>(enclosure.Members[0].Value.Value);
            Assert.IsTrue((int) enclosure.Members[0].Value.Value == 0);
            Assert.IsInstanceOf<bool>(methodCall.Parameters[4].Value);
            Assert.IsTrue((bool) methodCall.Parameters[4].Value);
        }

        [Test]
        public void ParseGetCategories()
        {
            var testCall =
                @"<?xml version=""1.0""?>
            <methodCall>
               <methodName>metaWeblog.getCategories</methodName>
               <params>
                   <param><value><string></string></value></param>
                   <param><value><string>bloget</string></value></param>
                   <param><value><string>Franklin</string></value></param>
               </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);
            Assert.IsTrue(methodCall.Name == MetaWebLog.MethodGetCategories);
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == string.Empty);
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin");
        }

        [Test]
        public void ParseGetBlogs()
        {
            const string testCall =
                @"<?xml version=""1.0""?>
            <methodCall><methodName>blogger.getUsersBlogs</methodName>
            <params>
            <param><value><string>blogid</string></value></param>
            <param><value><string>bloget</string></value></param>
            <param><value><string>Franklin</string></value></param>
            </params>
            </methodCall>";

            var methodCall = ParseMethodCall(testCall);
            Assert.IsTrue(methodCall.Name == Blogger.MethodGetUsersBlogs);
            Assert.IsTrue(methodCall.Parameters[0].Value.ToString() == "blogid");
            Assert.IsTrue(methodCall.Parameters[1].Value.ToString() == "bloget");
            Assert.IsTrue(methodCall.Parameters[2].Value.ToString() == "Franklin");
        }

        internal static XmlRpcMethodCall ParseMethodCall(string test)
        {
            var xmlSettings = new XmlReaderSettings
            {
                IgnoreComments = true,
                IgnoreProcessingInstructions = true,
                IgnoreWhitespace = true
            };

            using (var stringReader = new StringReader(test))
            {
                using (var xmlReader = XmlReader.Create(stringReader, xmlSettings))
                {
                    return XmlRpc.ReadMethod(xmlReader);
                }
            }
        }
    }
}